Skip to content

feat: enhanced Discord thread management#215

Closed
howie wants to merge 7 commits intoopenabdev:mainfrom
howie:claude/modest-kowalevski
Closed

feat: enhanced Discord thread management#215
howie wants to merge 7 commits intoopenabdev:mainfrom
howie:claude/modest-kowalevski

Conversation

@howie
Copy link
Copy Markdown

@howie howie commented Apr 11, 2026

Summary

Inspired by OpenClaw Discord Workflow, adds advanced thread management features to improve the Discord experience for multi-user environments.

Closes #188

New Features

  • Configurable auto-archive duration — Set auto_archive_duration to 60 (1h), 1440 (1d), 4320 (3d), or 10080 (1w). Previously hardcoded to 1 day.
  • Per-channel configuration — Each Discord channel can override global defaults via [discord.channels."<ID>"] sections in config.
  • Direct mode (require_mention = false) — Any message in the channel triggers a thread, no @mention needed. Ideal for dedicated bot channels.
  • Ignore other mentions (ignore_other_mentions = true) — Skip messages that mention other bots/users but not this bot. Prevents false triggers in multi-bot environments.
  • LLM-generated thread names (thread_name_mode = "generated") — After the main prompt completes, a background task asks the agent for a short title and renames the thread. Falls back to truncated name on failure (10s timeout).

Config Example

[discord]
auto_archive_duration = 1440
require_mention = true
ignore_other_mentions = false
thread_name_mode = "truncate"

[discord.channels."111111"]
require_mention = false
thread_name_mode = "generated"
auto_archive_duration = 60

Files Changed

  • src/config.rsChannelConfig struct, new fields on DiscordConfig, validation
  • src/discord.rs — Per-channel config resolution, direct mode, ignore logic, background thread naming
  • src/main.rs — Pass new config fields to Handler
  • config.toml.example — Document all new options
  • charts/openab/values.yaml — Helm values for new settings
  • charts/openab/templates/configmap.yaml — Template per-channel config

Known Limitations

  • Thread naming uses the same ACP session as the user conversation, which adds a naming turn to the session history. A dedicated lightweight API call would be cleaner but requires additional dependencies.
  • with_connection holds a global write lock during the naming request. Under high concurrent load with thread_name_mode = "generated", this may cause brief stalls for other threads.

Test plan

  • Deploy with default config — verify no behavioral change (backward compat)
  • Set auto_archive_duration = 60 — verify threads archive after 1 hour
  • Set require_mention = false on a channel — verify any message creates a thread
  • Set ignore_other_mentions = true — verify messages mentioning other bots are skipped
  • Set thread_name_mode = "generated" — verify thread gets renamed after first response
  • Test per-channel overrides with different settings per channel
  • Test invalid config values (e.g., auto_archive_duration = 999) — verify startup fails with clear error
  • helm template with new values — verify configmap output is correct

🤖 Generated with Claude Code

howie and others added 7 commits April 11, 2026 20:29
Adds `auto_archive_duration` to `DiscordConfig` with a default of 1440 (OneDay).
Validates at config load time that the value is one of 60/1440/4320/10080.
Passes the configured value through `Handler` to `get_or_create_thread` and
converts it to the appropriate `AutoArchiveDuration` enum variant.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
Add per-channel configuration overrides via `[discord.channels."ID"]`
TOML sections. Each channel can independently override:
- require_mention: when false, any message triggers the bot (direct mode)
- ignore_other_mentions: skip messages mentioning other users/bots
- auto_archive_duration: per-channel thread archive duration
- thread_name_mode: per-channel thread naming strategy

New global defaults on DiscordConfig: require_mention (true),
ignore_other_mentions (false), thread_name_mode ("truncate").
Channel overrides fall back to global defaults when not set.

Validation of auto_archive_duration also applies to channel overrides.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Use parent_channel_id (not thread ID) for per-channel config resolution
- Remove unused effective_* methods from DiscordConfig (logic is inline in Handler)
- Cache channel_override lookup to avoid repeated HashMap access

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
When thread_name_mode is set to "generated" (global or per-channel),
sends a short naming prompt to the ACP session after thread creation
and renames the thread via Discord API before the main response.
Falls back to the truncated name on any failure (timeout, error).

Includes config validation for thread_name_mode values at load time.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Run LLM thread naming after main prompt completes in a tokio::spawn task
  instead of blocking before stream_prompt. This avoids:
  - Holding the pool write-lock during the naming request
  - Delaying the user's response while a name is generated
  - The naming prompt appearing before the user's real message in session history
- Add "Do not use any tools" to naming prompt to prevent tool-use overhead
- Strip quotes and markdown formatting from generated names

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
… options

- config.toml.example: add require_mention, ignore_other_mentions,
  thread_name_mode, and per-channel override examples
- values.yaml: add discord.autoArchiveDuration, requireMention,
  ignoreOtherMentions, threadNameMode, and channels map
- configmap.yaml: template per-channel config with range loop

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@thepagent
Copy link
Copy Markdown
Collaborator

This is a large feature with per-channel config, direct mode, and background thread naming. Could you please create a Discord discussion thread and add the link to this PR description? This helps with design review and community feedback for bigger features. Thanks! 🙏

Copy link
Copy Markdown
Collaborator

@chaodu-agent chaodu-agent left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🔴 STALE — Requires full rewrite against current architecture. Cannot merge.

Baseline Check (Step 0)
Field Value
State OPEN
Mergeable CONFLICTING
Created 2026-04-11 (20 days ago)
Changes +256 / -15 across 6 files
Labels closing-soon

Main branch status: Since April 11, main underwent major refactoring:

  • AdapterRouter/ChatAdapter abstraction — discord.rs now uses trait-based adapter pattern
  • Handler struct completely different (new fields: router, allow_all_channels, allow_bot_messages, trusted_bot_ids, bot_turns, participated_threads, multibot_threads, allow_dm)
  • Thread creation moved to ChatAdapter trait method
  • shorten_thread_name moved to format.rs
Four-Question Framework

1. What problem does it solve?
Configurable thread management: auto-archive duration, require-mention toggle, ignore-other-mentions filter, LLM-generated thread names, per-channel config overrides.

2. How does it solve it?

  • 4 new config fields + per-channel ChannelConfig overrides
  • Config validation at load time
  • generate_thread_name / request_thread_name for LLM-based naming via background tokio::spawn
  • Passes auto_archive_duration through to thread creation
  • Updates Helm chart + config.toml.example

3. What was considered?
Per-channel overrides with global defaults (good layering), background thread naming with 10s timeout, input truncation for naming prompt.

4. Is it the best approach?
Design concepts are sound, but implementation targets a codebase that no longer exists.

Traffic Light

🟢 INFO

  • Config validation at startup with clear error messages — excellent fail-fast pattern
  • Per-channel override pattern is well-designed
  • Background thread naming with timeout is the right pattern

🔴 SUGGESTED CHANGES

  1. Structurally incompatible with current main — Targets pre-refactor architecture. Not a simple rebase — requires reimplementation against AdapterRouter/ChatAdapter pattern.
  2. generate_thread_name reuses session pool connection — Sends naming prompt through same ACP session, polluting conversation history. Should use separate ephemeral session.
  3. Thread name flash — Thread created with truncated name first, then renamed in background. Creates visible flash.

🟡 NIT

  1. thread_name_mode as String instead of enum — proper ThreadNameMode enum would be more idiomatic Rust
  2. Helm template boolean handling should use hasKey pattern (PR #639)

Recommendation: Close this PR. If the contributor wants to pursue these features, they should open a new PR based on current main and implement against the AdapterRouter/ChatAdapter pattern.

Reviewed by 超渡法師 🔃 chaodu Backlog triage

@chaodu-agent
Copy link
Copy Markdown
Collaborator

Closing — main has undergone major architectural refactoring (AdapterRouter/ChatAdapter abstraction) since this PR was opened. The feature concepts (auto-archive duration, per-channel config, LLM thread naming) are still valuable but would need to be reimplemented against the current architecture. Thanks for the contribution! 🙏

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

closing-soon PR missing Discord Discussion URL — will auto-close in 3 days pending-contributor

Projects

None yet

Development

Successfully merging this pull request may close these issues.

feat: enhanced Discord thread management (auto-thread, LLM naming, configurable archive)

3 participants